#include <algorithm>

#include "rational.h"

Rational& Rational::simplify() {
	int g = gcd(_numerator, _denominator);
	_numerator /= g;
	_denominator /= g;

	return *this;
}

Rational::Rational(const int numerator, const int denominator)
{
	_numerator = numerator;
	_denominator = denominator;
	this->simplify();
}

Rational::Rational(const Rational& r) {
	_numerator = r._numerator;
	_denominator = r._denominator;
}

Rational& Rational::operator= (const Rational& r) {
	_numerator = r._numerator;
	_denominator = r._denominator;

	return *this;
}

Rational& Rational::operator+= (const Rational& r) {
	_numerator = _numerator * r._denominator + r._numerator * _denominator;
	_denominator *= r._denominator;	

	return this->simplify();
}

Rational& Rational::operator-= (const Rational& r) {
	_numerator = _numerator * r._denominator - r._numerator * _denominator;
	_denominator *= r._denominator;	

	return this->simplify();
}

Rational& Rational::operator*= (const Rational& r) {
	_numerator *= r._numerator;
	_denominator *= r._denominator;

	return this->simplify();
}

Rational& Rational::operator/= (const Rational& r) {
	_numerator *= r._denominator;
	_denominator *= r._numerator;
	
	return this->simplify();
}

Rational& Rational::operator++() {
	_numerator += _denominator;

	return *this;
}

Rational Rational::operator++(int) {
	Rational temp(*this);

	++(*this);

	return temp;
}

Rational& Rational::operator--() {
	_numerator -= _denominator;

	return *this;

}
Rational Rational::operator--(int) {
	Rational temp(*this);

	--(*this);

	return temp;
}

Rational::operator double () {
	return 
		static_cast<double>(_numerator) /
		static_cast<double>(_denominator);
}

Rational operator- (const Rational& a, const Rational& b) {
	Rational temp(a);
	temp -= b;
	return temp;
}

Rational operator+ (const Rational& a, const Rational& b) {
	Rational temp(a);
	temp += b;
	return temp;
}

Rational operator* (const Rational& a, const Rational& b) {
	Rational temp(a);
	temp *= b;
	return temp;
}

Rational operator/ (const Rational& a, const Rational& b) {
	Rational temp(a);
	temp /= b;
	return temp;
}

bool operator== (const Rational& a, const Rational& b) {
	return 
		(a.numerator() == b.numerator()) &&
		(a.denominator() == b.denominator());
}

bool operator!= (const Rational& a, const Rational& b) {
	return !(a == b);
}

bool operator< (const Rational& a, const Rational& b) {
	return a.numerator() * b.denominator() < b.numerator() * b.denominator();	
}

bool operator>  (const Rational& a, const Rational& b) {
	return a.numerator() * b.denominator() > b.numerator() * b.denominator();	
}

bool operator<= (const Rational& a, const Rational& b) {
	return !(a>b);
}

bool operator>= (const Rational& a, const Rational& b) {
	return !(a<b);
}

int gcd(int a, int b) {
	int r1 = std::max(a,b);
	int r2 = std::min(a,b);

	while (r2 != 0) {
		std::swap(r1, r2);
		r2 = r2 % r1;
	}

	return r1;
}
